package tunafish2k.rpgex.items;

import java.util.List;
import java.util.Objects;

import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.attribute.EntityAttributes;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.inventory.StackReference;
import net.minecraft.item.BowItem;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.item.tooltip.TooltipType;
import net.minecraft.screen.slot.Slot;
import net.minecraft.sound.SoundCategory;
import net.minecraft.sound.SoundEvent;
import net.minecraft.sound.SoundEvents;
import net.minecraft.text.Text;
import net.minecraft.util.ClickType;
import net.minecraft.util.Hand;
import net.minecraft.util.Rarity;
import net.minecraft.util.TypedActionResult;
import net.minecraft.world.World;
import tunafish2k.rpgex.RpgEX;
import tunafish2k.rpgex.entities.StoneDartProjectile;
import tunafish2k.rpgex.registries.ComponentRegistry;
import tunafish2k.rpgex.registries.EntityRegistry;
import tunafish2k.rpgex.registries.ItemRegistry;

public class BlowPipeItem extends Item {
    public static final int ITEM_BASE_COOLDOWN = 20;
    public static final double PLAYER_BASE_ATTACK_SPEED = 4.0;
    public static final int AMMO_CAP = 16;

    public BlowPipeItem() {
        super(new Settings().maxDamage(512).maxCount(1).rarity(Rarity.COMMON));
    }

    @Override
    public TypedActionResult<ItemStack> use(World world, PlayerEntity user, Hand hand) {
        ItemStack itemStack = user.getStackInHand(hand);
        int ammo = getFilledAmmoCount(itemStack);
        boolean canUse = ammo > 0 || user.isInCreativeMode();
        if (!canUse)
            return TypedActionResult.fail(itemStack);
        user.getItemCooldownManager().set(this, (int) (ITEM_BASE_COOLDOWN * PLAYER_BASE_ATTACK_SPEED
                / user.getAttributeValue(EntityAttributes.GENERIC_ATTACK_SPEED)));
        shoot(world, user, itemStack);
        if (!user.isInCreativeMode()) {
            setFilledAmmoCount(itemStack, ammo - 1);
            itemStack.damage(1, user, LivingEntity.getSlotForHand(hand));
        }
        
        return TypedActionResult.success(itemStack);
    }

    public int getFilledAmmoCount(ItemStack itemStack) {
        Integer boxedAmmo = itemStack.get(ComponentRegistry.SINGLE_TYPE_AMMO);
        return Objects.isNull(boxedAmmo) ? 0 : boxedAmmo.intValue();
    }

    public void setFilledAmmoCount(ItemStack itemStack, int count) {
        itemStack.set(ComponentRegistry.SINGLE_TYPE_AMMO, count);
    }

    @Override
    public boolean onClicked(ItemStack stack, ItemStack otherStack, Slot slot, ClickType clickType, PlayerEntity player,
            StackReference cursorStackReference) {
        if (clickType != ClickType.LEFT || !stack.isOf(ItemRegistry.BLOW_PIPE)
                || !otherStack.isOf(ItemRegistry.STONE_DART)) {
            return super.onClicked(stack, otherStack, slot, clickType, player, cursorStackReference);
        }
        int currentAmmoCount = getFilledAmmoCount(stack);
        int holdingAmmoCount = otherStack.getCount();
        int fillAmmoCount = Math.min(AMMO_CAP - currentAmmoCount, holdingAmmoCount);
        setFilledAmmoCount(stack, currentAmmoCount + fillAmmoCount);
        otherStack.setCount(holdingAmmoCount - fillAmmoCount);
        player.getWorld().playSoundFromEntity((PlayerEntity) null, player,
                SoundEvents.ITEM_BOOK_PUT, SoundCategory.PLAYERS, 1.0F, 1.0F);
        return true;
    }

    @Override
    public void appendTooltip(ItemStack stack, TooltipContext context, List<Text> tooltip, TooltipType type) {
        tooltip.add(Text.translatable("item.rpgex.generic.lore.ammo_type", Text.translatable("item.rpgex.stone_dart")));
        tooltip.add(
                Text.translatable("item.rpgex.generic.lore.ammo_count", Integer.toString(getFilledAmmoCount(stack)), Integer.toString(AMMO_CAP)));
        tooltip.add(
                Text.translatable("item.rpgex.blow_pipe.lore.refill"));
        super.appendTooltip(stack, context, tooltip, type);
    }

    protected void shoot(World world, LivingEntity shooter, ItemStack blowPipeItemStack) {
        StoneDartProjectile projectile = new StoneDartProjectile(EntityRegistry.STONE_DART, shooter.getX(),
                shooter.getEyeY(), shooter.getZ(), shooter.getWorld(), new ItemStack(ItemRegistry.STONE_DART),
                blowPipeItemStack);
        projectile.setOwner(shooter);
        projectile.setVelocity(shooter, shooter.getPitch(), shooter.getYaw(), 0f, 1.5f, 1.0f);
        world.spawnEntity(projectile);
        world.playSound((PlayerEntity) null, shooter.getX(), shooter.getY(), shooter.getZ(),
                SoundEvents.ENTITY_ARROW_SHOOT, SoundCategory.PLAYERS, 1.0F,
                1.0F / (world.getRandom().nextFloat() * 0.4F + 1.2F) + 1.0F);
    }
}
